package org.yang.loginunion.core.wx.mp;

import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.yang.loginunion.core.LoginClient;
import org.yang.loginunion.core.constants.IdentityType;
import org.yang.loginunion.core.exception.LoginException;
import org.yang.loginunion.core.model.BindAuthCode;
import org.yang.loginunion.core.repository.OauthRepository;
import org.yang.loginunion.core.repository.OauthTempRepository;
import org.yang.loginunion.core.wx.mp.model.MpAccessToken;
import org.yang.loginunion.core.wx.mp.model.MpUserInfo;
import org.yang.loginunion.core.wx.mp.request.IMpRequest;

import java.util.List;
import java.util.Optional;

/**
 * * APP微信授权登录
 *
 * @author: Billyang
 * @date: 2024/8/10 15:02
 */
public class WeixinAppClient implements LoginClient {

    private OauthRepository oauthRepository;
    private OauthTempRepository oauthTempRepository;
    private IMpRequest mpRequest;

    public WeixinAppClient(OauthRepository oauthRepository, OauthTempRepository oauthTempRepository, IMpRequest mpRequest) {
        this.oauthRepository = oauthRepository;
        this.oauthTempRepository = oauthTempRepository;
        this.mpRequest = mpRequest;
    }

    /**
     * <pre>
     * 官网：https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Login/Development_Guide.html
     * </pre>
     */
    @Override
    public String login(String ignore3, String ignore2, String wxcode) {
        if (StringUtils.isBlank(wxcode)) {
            throw new LoginException("缺失参数");
        }

        MpAccessToken mpAccessToken = mpRequest.getAccessToken(wxcode);

        String openid = mpAccessToken.getOpenid();
        String accessToken = mpAccessToken.getAccessToken();
        String unionid = mpAccessToken.getUnionid();// 可能没有unionid，需要通过userinfo获取
        MpUserInfo userinfo = null;
        if (StringUtils.isBlank(unionid)) {
            userinfo = mpRequest.getUserinfo(accessToken, openid);
            unionid = userinfo.getUnionid();
        }

        //根据openid获取UserId
        String userId = oauthRepository.getUserId(IdentityType.WX_OPENID_APP, openid);
        if (userId == null) {
            // 根据unionid查询user_id
            if (StringUtils.isNotBlank(unionid)) {// 未绑定微信开放平台是没有unionid的
                userId = oauthRepository.getUserId(IdentityType.WX_UNIONID, unionid);
            }
            if (userId != null) {
                // unionid已经找到用户，但是openid没找到用户，自动做绑定
                oauthRepository.bindOauth(userId, IdentityType.WX_OPENID_APP, openid, wxcode);
            }
        } else {
            // openid已经找到用户，如果unionid没找到用户的话自动做绑定
            if (StringUtils.isNotBlank(unionid)) {// 未绑定微信开放平台是没有unionid的
                String userId2 = oauthRepository.getUserId(IdentityType.WX_UNIONID, unionid);
                if (userId2 == null) {
                    oauthRepository.bindOauth(userId, IdentityType.WX_UNIONID, unionid, wxcode);
                }
            }
        }

        if (userId == null) {
            // 说明微信没有绑定账号，需前端跳转到手机号+验证码登录(MOBILE_CODE_BIND)，并携带信息可以方便后续找到openid，unionid和用户信息
            if (userinfo == null) {
                userinfo = mpRequest.getUserinfo(accessToken, openid);
            }
            // 存储BindAuthCode相关信息
            BindAuthCode bindAuthCode = new BindAuthCode();
            bindAuthCode.setNickname(Optional.ofNullable(userinfo).map(MpUserInfo::getNickname).orElse(null));
            bindAuthCode.setHeadimgurl(Optional.ofNullable(userinfo).map(MpUserInfo::getHeadimgurl).orElse(null));
            List<BindAuthCode.BindUserOauth> binds = Lists.newArrayList();
            binds.add(new BindAuthCode.BindUserOauth().setIdentityType(IdentityType.WX_OPENID_APP)
                    .setIdentifier(openid));
            binds.add(
                    new BindAuthCode.BindUserOauth().setIdentityType(IdentityType.WX_UNIONID).setIdentifier(unionid));
            bindAuthCode.setBinds(binds);
            oauthTempRepository.saveBindAuthCode(wxcode, bindAuthCode);

            // 微信没有绑定账号
            return null;
        }

        return userId;
    }
}
